#______________________________________________________________________________#
#                           --PARSER FINAL---                                  #
#    # Grupo: Grog xD                                                          #
#    # Integrantes:                                                            #
#           -Alejandro Julian                                                  #
#           -Marcos Federico Mandrille                                         #
#           -Mauricio Nazzetta                                                 #
#           -Nicolas Nocete                                                    #
#______________________________________________________________________________#

#   Inclusion de unidades requeridas
import xml.etree.ElementTree as e   #Unidad encargada de manejo del elementtree
import Pascal_Mantenimiento as clean#Modulo de mantenimiento de carpetas
#______________________________________________________________________________#
#                                   INICIO                                     #
#______________________________________________________________________________#
#Definicion de clases
class C_cargador: #Clase que llevara toda la info que necesitamos
    def __init__ (self):
        self = self
#______________________________________________________________________________#
#Definicion de funciones
def Parser_Tree(t): #Lectura recursiva del arbol
    tab=""
    if 1 == 2: print("Matematicas locas xD")
    elif t.tag == "types": p.cod.write(Create_Type(t) + "\n")
    elif t.tag == "consts": p.cod.write(Create_Const(t) + "\n")
    elif t.tag == "vars": p.cod.write(Create_Var(t) + "\n")
    elif t.tag == "uses": p.cod.write(Create_Uses(t) + "\n\n" + "type" + "\n\t" + "TForm1 = class(TForm)" + "\n\t\t" + "procedure FormCreate(Sender: TObject);" + "\n\t" + "private" + "\n\t\t" + "{ Private Declaration }" + "\n\t" + "public" + "\n\t\t" + "{ Public Declaration }" + "\n\t" + "end;" + "\n\n" + "var" + "\n\t" + "Form1: TForm1;" + "\n\n" + "implementation" + "\n\n" + "{$R *.dfm}" + "\n\n" + "procedure TForm1.FormCreate(Sender: TObject);" + "\n\n")
    elif t.tag == "main": p.cod.write(Create_Program(t))
    elif t.tag in ["procedure","function"]: p.cod.write(Create_Subprogram(t) + "\n")
    elif t.tag == "begin": p.cod.write(Create_Begin(t,tab) + ";")

    if not(t.tag in ["procedure","function"]):
        for x in t.getchildren():
            x.padre = t #Me permite luego  volver arriba en cualquier momento...
            Parser_Tree(x)

#Funciones creadas para el procesamiento del arbol segun el caso.
def Create_Program(fruta):
    return("unit " + fruta.attrib["name"] + ";\n\n" + "interface" + "\n\n")

def Create_Uses(fruta):
    codigo = "uses" + "\n\t" + "Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs"
    for unit in fruta.getchildren():
        codigo += ", " + unit.attrib["name"]
    return(codigo + ";")

def Create_Type(fruta):
    codigo = "type" + "\n\t"
    for tipe in fruta.getchildren():
        codigo += tipe.attrib["name"] + " = "
        if tipe.attrib.has_key("tamano"): codigo += tipe.attrib["type"] + "[" + tipe.attrib["tamano"] + "];" + "\n\t"
        elif tipe.attrib.has_key("type") and (tipe.attrib["type"] == "enumeracion"): codigo += "(" + tipe.attrib["range"][1:-1] + ");" + "\n\t"
        elif tipe.attrib.has_key("range"): codigo += tipe.attrib["range"] + ";" + "\n\t"
        elif tipe.attrib.has_key("type"): codigo += tipe.attrib["type"] + ";\n\t"
        elif len(tipe.attrib) == 1: #Este es el caso del record
            codigo += "record" + "\n\t\t"
            for atributo in tipe.getchildren():
                codigo += atributo.attrib["name"] + " = " + atributo.attrib["type"] + ";\n\t\t"
            codigo = codigo[0:-1] + "\n\t" + "end;" +"\n\t"
    return(codigo)

def Create_Const(fruta):
    codigo = "const" + "\n\t"
    for sub_var in fruta.getchildren():
        codigo += sub_var.attrib["name"] + " = " + sub_var.attrib["value"] + ";\n\t"
    return(codigo)

def Create_Var(fruta):
    def Create_Array(fruta):
        codigo = "["
        for rango in fruta.getchildren():
            if rango.tag == "range":
                if not(codigo=="["): codigo += ","
                if len(rango.getchildren()) == 2: codigo += rango.getchildren()[0].attrib["inicio"] + ".." + rango.getchildren()[1].attrib["fin"]
                else: codigo += rango.getchildren()[0].attrib["var"]
            else: codigo += "] of " + fruta.tag + Create_Array(rango)
        if not(";" in codigo): codigo += "] of " + fruta.tag + ";"
        return(codigo)
    #Funcionamiento Basico al encontrar conjunto de variables
    codigo = "var" + "\n\t"
    for sub_var in fruta.getchildren():
        if sub_var.attrib.has_key("type"): codigo += sub_var.attrib["name"] + ": array"
        else: codigo += sub_var.attrib["name"] + " : " + sub_var.attrib["date_type"]
        if sub_var.attrib.has_key("type") and sub_var.attrib["type"] == "array": codigo += Create_Array(sub_var.getchildren()[0])
        else: codigo += ";"
        codigo += "\n\t"
    return(codigo)

def Create_Subprogram(fruta):
    tab = ""
    codigo = fruta.attrib["name"] + "("
    for param in fruta.find("param").getchildren():
        codigo += param.attrib["name"] + ":" + param.attrib["type"] + ", "
    codigo = codigo[0:-2] + ")"
    if fruta.tag == "procedure": codigo += ";" + "\n"
    else: codigo += ":" + fruta.find("result").attrib["type"] + ";" + "\n"
    if not(fruta.find("types") == None): codigo+= (Create_Type(fruta.find("types")) + "\n")
    if not(fruta.find("consts") == None): codigo+= (Create_Const(fruta.find("consts")) + "\n")
    if not(fruta.find("vars") == None): codigo+= (Create_Var(fruta.find("vars")) + "\n")
    if not(fruta.find("begin") == None): codigo+= (Create_Begin(fruta.find("begin"),"") + ";\n")
    return(codigo + "\n" )

def Create_Begin(fruta,tab):
    tab+= "\t"
    codigo = ""
    if not(fruta.tag == "repeat"):codigo = tab[0:-1] + "begin" + "\n"
    for item in fruta.getchildren():
        if item.tag == "exp": codigo+= tab + Create_Asignacion(item) + ";\n"
        elif item.tag == "call": codigo+= tab + Create_Llamado(item) + ";\n"
        elif item.tag == "for": codigo+= tab + Create_For(item,tab) + ";\n"
        elif item.tag == "while": codigo+= tab + Create_While(item,tab) + ";\n"
        elif item.tag == "repeat": codigo+= tab + Create_Repeat(item,tab) + ";\n"
        elif item.tag == "if": codigo+= tab + Create_If(item,tab) + ";\n"
        elif item.tag == "case": codigo+= tab + Create_Case(item,tab) + ";\n"
    if not(fruta.tag == "repeat"): codigo+= tab[0:-1] + "end"
    return(codigo)

def Create_Asignacion(fruta):
    codigo = fruta.find("lvalue").attrib["id"]
    if not((fruta.find("lvalue").find("index") == None)):
        codigo += "[" + Create_Operacion(fruta.find("lvalue").find("index").getchildren()[0]) + "]"
    codigo += " := " + Create_Operacion(fruta.getchildren()[1])
    return(codigo)

def Create_Operacion(fruta):
    if len(fruta.getchildren())==0: return(fruta.attrib.values()[0])
    elif "function" in fruta.attrib.keys(): return(Create_Llamado(fruta))
    elif len(fruta.getchildren())==1: return("-(" + Create_Operacion(fruta.getchildren()[0]) + ")")
    elif (len(fruta.getchildren()[0])==2) and (len(fruta.getchildren()[1])==2): return("(" + Create_Operacion(fruta.getchildren()[0]) + " " + fruta.attrib["op"] + " " + Create_Operacion(fruta.getchildren()[1]) + ")")
    elif (len(fruta.getchildren()[0])==0) and (len(fruta.getchildren()[1])==0): return("(" + fruta.getchildren()[0].attrib["id"] + " " + fruta.attrib["op"] + " " + fruta.getchildren()[1].attrib["id"] + ")")
    elif (len(fruta.getchildren()[0])==0) and (len(fruta.getchildren()[1])==2) and (fruta.getchildren()[1].tag == "call"): return("(" + fruta.getchildren()[0].attrib["id"] + " " + fruta.attrib["op"] + " " + Create_Llamado(fruta.getchildren()[1]) + ")")
    elif (len(fruta.getchildren()[0])==0) and (len(fruta.getchildren()[1])==2): return("(" + fruta.getchildren()[0].attrib["id"] + " " + fruta.attrib["op"] + " " + Create_Operacion(fruta.getchildren()[1]) + ")")
    elif (len(fruta.getchildren()[0])==2) and (len(fruta.getchildren()[1])==0) and (fruta.getchildren()[0].tag == "call"): return("(" + Create_Llamado(fruta.getchildren()[0]) + " " + fruta.attrib["op"] + " " + fruta.getchildren()[1].attrib["id"] + ")")
    elif (len(fruta.getchildren()[0])==2) and (len(fruta.getchildren()[1])==0): return("(" + Create_Operacion(fruta.getchildren()[0]) + " " + fruta.attrib["op"] + " " + fruta.getchildren()[1].attrib["id"] + ")")

def Create_Llamado(fruta):

    if fruta.attrib.values()[0] == "writeln": codigo = "ShowMessage"  "("
    else: codigo = fruta.attrib.values()[0] + "("
    for param in fruta.getchildren():
        codigo+= Create_Operacion(param) + ","

    if fruta.attrib.values()[0] == "readln": codigo = fruta.find("param").attrib["id"] + ":= InputBox('InputBox','Ingrese la cadena deseada','')"
    return(codigo[0:-1] + ")")

def Create_For(fruta,tab):
    codigo = "for" + " " + fruta.find("params").getchildren()[0].attrib["id"] + " := " + Create_Operacion(fruta.find("params").getchildren()[1]) + " to " + Create_Operacion(fruta.find("params").getchildren()[2]) + " do" + "\n"
    codigo+= Create_Begin(fruta,tab)
    return(codigo)

def Create_While(fruta,tab):
    codigo = "while" + " " + Create_Operacion(fruta.find("condition")) + " do" + "\n"
    codigo+= Create_Begin(fruta,tab)
    return(codigo)

def Create_Repeat(fruta,tab):
    codigo = "repeat" + "\n"
    codigo+= Create_Begin(fruta,tab)
    codigo+= tab + "until " + Create_Operacion(fruta.find("condition"))
    return(codigo)

def Create_If(fruta,tab):
    codigo = "if " + Create_Operacion(fruta.find("condition")) + " then" + "\n"
    codigo+= Create_Begin(fruta,tab)
    if fruta.find("else"): codigo+= "\n" + tab + "else" + "\n" + Create_Begin(fruta.find("else"),tab)
    return(codigo)

def Create_Case(fruta,tab):
    codigo = "case " + fruta.attrib["var"] + " of"
    tab+= "\t"
    for opcion in fruta.getchildren():
        codigo+= "\n" + tab + opcion.attrib["constante"] + ":"
        codigo+= "\n" + Create_Begin(opcion,tab) + ";"
    codigo+= "\n" + tab[0:-1] + "end"
    return(codigo)

tree = e.parse("Resultados\Codigo_intermedio.xhtml") #Cargamos el xml en el objeto p
tree.root = tree.getroot() #generamos el cabezal para laburar...
p = C_cargador()
if clean.os.path.isfile("Resultados\Codigo_Final.pas"): clean.os.remove("Resultados\Codigo_Final.pas")

p.cod=open("Resultados\Codigo_Final.pas","a")

Parser_Tree(tree.root)

p.cod.write("\n" + "end.")

p.cod.close()

clean.Eliminar("*.pyc")
